package com.demomaster.quickaccessibility.service;

import android.Manifest;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.GestureDescription;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.ContentResolver;
import android.content.Context;
import android.graphics.Path;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;

import com.demomaster.quickaccessibility.utils.DisplayUtil;
import com.demomaster.quickaccessibility.utils.QdThreadHelper;
import com.demomaster.quickaccessibility.utils.ServiceHelper;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * 无障碍服务帮助类
 */
public class QuickAccessibilityHelper {
    private static String TAG = QuickAccessibilityHelper.class.getSimpleName();
    //开启无障碍服务,需要WRITE_SECURE_SETTINGS权限
    public static void openAccessibilityService(Context context, Class<? extends AccessibilityService> service) {
        String serviceClassName = service.getCanonicalName();
        try {
            Log.d(TAG, ServiceHelper.serverIsRunning(context, service.getName()) ? "无障碍服务【已开启】" : "无障碍服务【未开启】");
            String targetID = context.getPackageName() + "/" + serviceClassName;
            ContentResolver contentResolver = context.getApplicationContext().getContentResolver();
            String enabledServices = Settings.Secure.getString(contentResolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
            //Log.d(TAG,TAG,"无障碍的辅助服务 enabledServices："+enabledServices);
            String newValue = "";
            if (TextUtils.isEmpty(enabledServices)) {
                newValue = targetID;
            } else if (!enabledServices.contains(targetID)) {
                newValue = enabledServices + ":" + targetID;
            }
            if (enabledServices.contains(targetID)) {
                newValue = enabledServices;
            }
            //Log.d(TAG,TAG,"无障碍的辅助服务 newValue："+newValue);
            Settings.Secure.putString(contentResolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, newValue);
            Settings.Secure.putString(contentResolver, Settings.Secure.ACCESSIBILITY_ENABLED, "1");
            String strs = Settings.Secure.getString(contentResolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
            Log.d(TAG,"无障碍辅助服务值：" + strs);
        } catch (Exception e) {
            //授权方法：开启usb调试并使用adb工具连接手机，执行 adb shell pm grant org.autojs.autojspro android.permission.WRITE_SECURE_SETTING
            //QdToast.show(context.getApplicationContext(),"请确保已给予 WRITE_SECURE_SETTINGS 权限授权代码已复制，请使用adb工具连接手机执行(重启不失效)"+ e.toString());
            //QDLogger.e("adb shell pm grant "+context.getApplicationContext().getPackageName()+" android.permission.WRITE_SECURE_SETTINGS"+",e="+e.toString());
            Log.e(TAG,e.toString());
        }
    }

    /**
     * 根据正则表达式返回匹配的节点列表
     *
     * @param nodeInfo
     * @param text
     * @return
     */
    public static List findListByRegex(AccessibilityNodeInfo nodeInfo, String text) {
        List<AccessibilityNodeInfo> result = new ArrayList<>();
        if (nodeInfo != null && nodeInfo.isVisibleToUser() && !TextUtils.isEmpty(text)) {
            if (!TextUtils.isEmpty(nodeInfo.getText())) {
                //Log.d(TAG,"nodeInfo isFocusable="+nodeInfo.isFocusable()+",isVisibleToUser="+nodeInfo.isVisibleToUser()+",text="+nodeInfo.getText());
                // 创建Pattern对象，表示要匹配的正则表达式
                Pattern pattern = Pattern.compile(text);
                // 使用Pattern对象的matcher方法获取Matcher对象
                Matcher matcher = pattern.matcher(nodeInfo.getText());
                // 使用Matcher对象的find方法查找匹配的字符串
                if (matcher.find()) {
                    result.add(nodeInfo);
                }
            }
            int count = nodeInfo.getChildCount();
            for (int i = 0; i < count; i++) {
                result.addAll(findListByRegex(nodeInfo.getChild(i), text));
            }
        }
        return result;
    }

    /**
     * 根据正则表达式匹配1个节点
     *
     * @param nodeInfo
     * @param text
     * @return
     */
    public static AccessibilityNodeInfo findOneByRegex(AccessibilityNodeInfo nodeInfo, String text) {
        if (nodeInfo != null && nodeInfo.isVisibleToUser() && !TextUtils.isEmpty(text)) {
            Rect rect1 = new Rect(0, 0, DisplayUtil.getScreenWidth(QuickAccessibilityService.instance.getApplicationContext()), DisplayUtil.getScreenHeight(QuickAccessibilityService.instance.getApplicationContext()));
            Rect rect2 = QuickAccessibilityHelper.getBundsInScreen(nodeInfo);
            if (rect2 != null && rect1.intersect(rect2)) {//过滤当前屏幕内的节点
                if (!TextUtils.isEmpty(nodeInfo.getText())) {
                    Pattern pattern = Pattern.compile(text);
                    Matcher matcher = pattern.matcher(nodeInfo.getText());
                    if (matcher.find()) {
                        return nodeInfo;
                    }
                }
                int count = nodeInfo.getChildCount();
                if (count > 0) {
                    for (int i = count - 1; i >= 0; i--) {//这里绘制存在覆盖关系，为了得到最上层的控件 需要倒序
                        AccessibilityNodeInfo accessibilityNodeInfo = findOneByRegex(nodeInfo.getChild(i), text);
                        if (accessibilityNodeInfo != null) {
                            return accessibilityNodeInfo;
                        }
                    }
                }
            }
        }
        return null;
    }


    /**
     * 查询指定边界范围内可点击得view
     *
     * @param parent
     * @param rect
     * @return
     */
    public static AccessibilityNodeInfo findClickAbleNodeInRect(AccessibilityNodeInfo parent, Rect rect) {
        if (parent != null) {
            int count = parent.getChildCount();
            for (int i = 0; i < count; i++) {
                AccessibilityNodeInfo child = parent.getChild(i);
                if (child.isClickable()) {
                    Rect rect1 = getBundsInScreen(child);
                    if (rect.contains(rect1)) {
                        return child;
                    }
                }
            }
        }
        return null;
    }

    /**
     * 查询指定边界范围内可点击得view
     *
     * @param parent
     * @return
     */
    public static AccessibilityNodeInfo findClickAbleNodeWithPositionLeft(AccessibilityNodeInfo parent, int left) {
        if (parent != null) {
            int count = parent.getChildCount();
            for (int i = 0; i < count; i++) {
                AccessibilityNodeInfo child = parent.getChild(i);
                if (child != null && child.isClickable()) {
                    Rect rect1 = new Rect();
                    child.getBoundsInScreen(rect1);
                    if (rect1.left == left) {
                        Log.d(TAG,"rect2=" + rect1 + "," + child);
                        return child;
                    }
                }
            }
        }
        return null;
    }

    public static boolean touchClick(AccessibilityNodeInfo nodeInfo) {
        Log.d(TAG, "点触：Id=" + nodeInfo.getViewIdResourceName() + ",Text=" + nodeInfo.getText() + ",Description=" + nodeInfo.getContentDescription() + ",ClassName=" + nodeInfo.getClassName() + ",isVisibleToUser=" + nodeInfo.isVisibleToUser() + ",getDrawingOrder=" + nodeInfo.getDrawingOrder());
        //&& nodeInfo.isVisibleToUser()
        if (!clickNode(nodeInfo)) {
            return touchNode(nodeInfo);
        }
        if (!touchNode(nodeInfo)) {
            return clickNode(nodeInfo);
        }
        return false;
    }

    /**
     * 获取节点边界矩形信息
     *
     * @param nodeInfo
     * @return
     */
    public static Rect getBundsInScreen(AccessibilityNodeInfo nodeInfo) {
        if (nodeInfo != null) {
            Pattern pattern = Pattern.compile("boundsInScreen\\s*:\\s*Rect\\((\\d+),\\s*(\\d+)\\s*-\\s*(\\d+),\\s*(\\d+)\\);");
            Matcher matcher = pattern.matcher(nodeInfo.toString());
            if (matcher.find()) {
                int x = Integer.parseInt(matcher.group(1));
                int y = Integer.parseInt(matcher.group(2));
                int width = Integer.parseInt(matcher.group(3));
                int height = Integer.parseInt(matcher.group(4));
                //System.out.println("boundsInScreen: x=" + x + ", y=" + y + ", width=" + width + ", height=" + height);
                return new Rect(x, y, width, height);
            } else {
                Rect rect = new Rect();
                nodeInfo.getBoundsInScreen(rect);
                System.out.println("未找到boundsInScreen信息 rect=" + rect);
                return rect;
            }
        }
        return null;
    }

    public static void stop() {
        if (QuickAccessibilityService.instance != null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                QuickAccessibilityService.instance.disableSelf();
            }
        }
    }

    public static boolean isInScreen(AccessibilityNodeInfo lijiqiandao) {
        if (lijiqiandao != null && lijiqiandao.isVisibleToUser()) {
            int screenWidth = DisplayUtil.getScreenWidth(QuickAccessibilityService.instance.getApplicationContext());
            int screenHeight = DisplayUtil.getScreenHeight(QuickAccessibilityService.instance.getApplicationContext());
            //Rect screenRect = new Rect(0,0,screenWidth,screenHeight);
            Rect rect = getBundsInScreen(lijiqiandao);
            if (rect != null) {
                return (rect.top >= 0 && rect.top <= screenHeight) || (rect.bottom >= 0 || rect.bottom <= screenHeight);
            }
        }
        return false;
    }

    public static void startSettintActivity(Context context) {
         /*Intent intent = new Intent(context, DialogWindowActivity.class);
        Bundle bundle = new Bundle();
        bundle.putString("permission", Manifest.permission.BIND_ACCESSIBILITY_SERVICE);
        intent.putExtras(bundle);
        (context).startActivity(intent);*/
        //TODO QuickPermission.with().permissions(Manifest.permission.BIND_ACCESSIBILITY_SERVICE).request();
    }

    /**
     * 判断是否存在置顶的无障碍服务
     *
     * @param clazz
     * @return
     */
    public boolean isAccessibilityServiceRunning(Context context, Class<? extends QuickAccessibilityService> clazz) {
        String name = clazz.getCanonicalName();
        String targetId = context.getPackageName() + "/" + name;
        AccessibilityManager am = (AccessibilityManager) context.getApplicationContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
        int accessibilityEnabled = 0;
        ContentResolver contentResolver = context.getApplicationContext().getContentResolver();
        try {
            String enabledServices = Settings.Secure.getString(contentResolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
            Log.d(TAG,"已开启的无障碍服务：" + enabledServices);
            accessibilityEnabled = Settings.Secure.getInt(contentResolver, Settings.Secure.ACCESSIBILITY_ENABLED);//"1开启":"0关闭"
        } catch (Settings.SettingNotFoundException e) {
            Log.e(TAG,e.toString());
        }
        List<AccessibilityServiceInfo> enableServices = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC);
        if (accessibilityEnabled == 1) {
            if (enableServices != null) {
                for (AccessibilityServiceInfo enableService : enableServices) {
                    Log.d(TAG,"当前服务：" + enableService.getId() + ",目标服务：" + targetId);
                    if (enableService.getId().trim().equalsIgnoreCase(targetId.trim())) {
                        Log.d(TAG,"服务已开启：" + targetId);
                        return true;
                    }
                }
            } else {
                Log.e(TAG,"FEEDBACK_GENERIC " + enableServices.toString() + "不包含" + targetId);
            }
        }
        return false;
    }

    /**
     * 判断无障碍辅助功能是否开启
     *
     * @param context
     * @return
     */
    public static boolean isAccessBilityOn(Context context,Class clazz) {
        String service = context.getPackageName() + "/" + clazz.getCanonicalName();// InstallService.class.getCanonicalName();
        try {
            int i = Settings.Secure.getInt(context.getApplicationContext().getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);
            if (i == 1) {
                String settingVlue = Settings.Secure.getString(context.getApplicationContext().getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
                String[] arr = settingVlue.split(":");
                if (arr.length > 0) {
                    for (String name : arr) {
                        if (service.equalsIgnoreCase(name)) {
                            return true;
                        }
                    }
                }
            }
        } catch (Settings.SettingNotFoundException e) {
            Log.e(TAG,e.toString());
        }
        return false;
    }

    /**
     * 判断服务是否开启
     *
     * @param context
     * @param clazz
     * @return
     */
    public static boolean isEnable(Context context, Class<? extends AccessibilityService> clazz) {
        String name = context.getPackageName() + "/" + clazz.getCanonicalName();
        AccessibilityManager am = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
        List<AccessibilityServiceInfo> serviceInfos = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC);
        //List<AccessibilityServiceInfo> installedAccessibilityServiceList = am.getInstalledAccessibilityServiceList();
        if (serviceInfos != null) {
            for (AccessibilityServiceInfo serviceInfo : serviceInfos) {
                if (name.equals(serviceInfo.getId())) {
                    //QDLogger.e("无障碍服务已开启："+name);
                    return true;
                }
            }
        }
        return false;
    }

    public static List<AccessibilityNodeInfo> findNodesByViewClass(AccessibilityNodeInfo nodeInfo, String viewClass) {
        if (nodeInfo != null) {
            List<AccessibilityNodeInfo> list = new ArrayList<>();
            if (nodeInfo.getClassName().equals(viewClass)) {
                list.add(nodeInfo);
            }
            int count = nodeInfo.getChildCount();
            if (count > 0) {
                for (int i = 0; i < count; i++) {
                    List<AccessibilityNodeInfo> list2 = findNodesByViewClass(nodeInfo.getChild(i), viewClass);
                    if (list2 != null) {
                        list.addAll(list2);
                    }
                }
            }
            return list;
        }
        return null;
    }

    public static void autoInput(Context context, AccessibilityNodeInfo nodeInfo, String text) {
        if (nodeInfo == null) {
            return;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//Android 5.0 版本及以上：
            QdThreadHelper.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Bundle arguments = new Bundle();
                    arguments.putCharSequence(
                            AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
                    nodeInfo.performAction(AccessibilityNodeInfo.ACTION_FOCUS);
                    boolean b = nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
                    Log.e("auto", "自动输入:" + text + "," + b);
                }
            });
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {//Android 4.3 版本及以上：
            ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
            ClipData clip = ClipData.newPlainText("label", text);
            clipboard.setPrimaryClip(clip);
            CharSequence txt = nodeInfo.getText();
            Bundle arguments = new Bundle();
            arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 0);
            arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, text.length());
            nodeInfo.performAction(AccessibilityNodeInfo.ACTION_FOCUS);
            nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments);
            nodeInfo.performAction(AccessibilityNodeInfo.ACTION_PASTE);
        }

//        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
//        imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
//        // 自动输入预定义的文本
//        InputConnection ic = event.getParcelableData().open输入法(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE, null);
//        ic.commitText("这是一段自动输入的文本", 1);
//        ic.close();
    }

    public static boolean clickNode(AccessibilityNodeInfo nodeInfo1) {
        AccessibilityNodeInfo nodeInfo = findClickAbleNode(nodeInfo1);
        if (nodeInfo != null) {
            //Log.i(TAG, "点击[" + item.getText() + "]:" + item.getViewIdResourceName());
            return nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        }
        return false;
    }

    public static boolean clickNode2(AccessibilityNodeInfo nodeInfo1) {
        if (nodeInfo1 != null) {
            //Log.i(TAG, "点击[" + item.getText() + "]:" + item.getViewIdResourceName());
            return nodeInfo1.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        }
        return false;
    }

    public static void longClickNode(AccessibilityNodeInfo nodeInfo1) {
        AccessibilityNodeInfo nodeInfo = findClickAbleNode(nodeInfo1);
        // 执行长按操作
        if (nodeInfo != null) {
            //Log.i(TAG, "点击[" + item.getText() + "]:" + item.getViewIdResourceName());
            nodeInfo.performAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
        } else {
            Log.i(TAG, "未找到可点击按钮");
        }
    }


    public static AccessibilityNodeInfo findClickAbleNode(AccessibilityNodeInfo item) {
        if (item != null) {
            if (item.isClickable() && item.isEnabled()) {
                return item;
            } else {
                AccessibilityNodeInfo parent = item.getParent();
                return findClickAbleNode(parent);
            }
        }
        return null;
    }

    public static List<AccessibilityNodeInfo> findListById(AccessibilityService accessibilityService, String idstr) {
        if (accessibilityService != null) {
            return findListById(accessibilityService.getRootInActiveWindow(), idstr);
        }
        return null;
    }

    public static List<AccessibilityNodeInfo> findListById(AccessibilityNodeInfo parentNode, String idstr) {
        List<AccessibilityNodeInfo> list = null;
        if (!TextUtils.isEmpty(idstr)) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                if (parentNode != null) {
                    list = parentNode.findAccessibilityNodeInfosByViewId(idstr);
                }
            }
        }
        return list;
    }

    /**
     * 根据id查询视图节点
     *
     * @param parentNode
     * @param idstr
     * @return
     */
    public static AccessibilityNodeInfo findOneById(AccessibilityNodeInfo parentNode, String idstr) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            if (!TextUtils.isEmpty(idstr)) {
                if (parentNode != null) {
                    List<AccessibilityNodeInfo> nodeInfoList = parentNode.findAccessibilityNodeInfosByViewId(idstr);
                    if (nodeInfoList != null && nodeInfoList.size() > 0) {
                        return nodeInfoList.get(0);
                    }
                }
            }
        }

        List<AccessibilityNodeInfo> nodeInfoList = findListById(parentNode, idstr);
        if (nodeInfoList != null && nodeInfoList.size() > 0) {
            return nodeInfoList.get(0);
        }
        return null;
    }

    public static AccessibilityNodeInfo findOneByDescribe(AccessibilityNodeInfo pNode, String text) {
        AccessibilityNodeInfo nodeInfo = null;
        if (!TextUtils.isEmpty(text) && (pNode != null)) {
            //如果查不到 则使用自定义遍历查询
            nodeInfo = findOneByDescribeEquals(pNode, text);
        }
        return nodeInfo;
    }

    public static AccessibilityNodeInfo findOneByDescribeEquals(AccessibilityNodeInfo pNode, String text) {
        if (!TextUtils.isEmpty(text) && (pNode != null)) {
            //判断是否在当前屏幕
            Rect rect1 = new Rect(0, 0, DisplayUtil.getScreenWidth(QuickAccessibilityService.instance.getApplicationContext()), DisplayUtil.getScreenHeight(QuickAccessibilityService.instance.getApplicationContext()));
            Rect rect2 = QuickAccessibilityHelper.getBundsInScreen(pNode);
            if (rect2 != null && rect1.intersect(rect2)) {
                //如果查不到 则使用自定义遍历查询
                if (!TextUtils.isEmpty(pNode.getContentDescription()) && pNode.getContentDescription().equals(text)) {
                    return pNode;
                }
                int count = pNode.getChildCount();
                for (int i = count - 1; i >= 0; i--) {
                    AccessibilityNodeInfo nodeInfo = findOneByDescribeEquals(pNode.getChild(i), text);
                    if (nodeInfo != null) {
                        return nodeInfo;
                    }
                }
            }
        }
        return null;
    }


    public static List<AccessibilityNodeInfo> findListByText(AccessibilityNodeInfo pNode, String text) {
        List<AccessibilityNodeInfo> list = new ArrayList<>();
        if (!TextUtils.isEmpty(text) && (pNode != null)) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                List<AccessibilityNodeInfo> list2 = pNode.findAccessibilityNodeInfosByText(text);
                if (list2.size() > 0) {
                    list.addAll(list2);
                    return list;
                }
            }
            //如果查不到 则使用自定义遍历查询
            if (!TextUtils.isEmpty(pNode.getText()) && pNode.getText().equals(text)) {
                list.add(pNode);
            }
            int count = pNode.getChildCount();
            for (int i = count - 1; i >= 0; i--) {
                list.addAll(findListByText(pNode.getChild(i), text));
            }
        }
        return list;
    }

    /**
     * 是否包含text的子节点
     *
     * @return
     */
    public static boolean containsChildNodeByText(AccessibilityNodeInfo nodeInfo, String text) {
        if (nodeInfo != null) {
            List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText(text);
            return list != null && list.size() > 0;
        }
        return false;
    }

    /**
     * 是否包含id的子节点
     *
     * @return
     */
    public static boolean containsChildNodeById(AccessibilityNodeInfo nodeInfo, String id) {
        if (nodeInfo != null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId(id);
                return list != null && list.size() > 0;
            }
        }
        return false;
    }

    public static boolean touchNode(AccessibilityNodeInfo nodeInfo1) {
        if (nodeInfo1 != null) {
            GestureDescription.Builder builder = new GestureDescription.Builder();
            try {
                Random random = new Random();
                long duration = 120 + random.nextInt(60);
                Path path = new Path();
                Rect rect = getBundsInScreen(nodeInfo1);
                int screenWidth = DisplayUtil.getScreenWidth(QuickAccessibilityService.instance);
                int screenHeight = DisplayUtil.getScreenHeight(QuickAccessibilityService.instance);
                Rect screenRect = new Rect(0, 0, screenWidth, screenHeight);
                if (screenRect.intersect(rect)) {
                    int l = random.nextInt(rect.width()) + rect.left;
                    int t = random.nextInt(rect.height()) + rect.top;
                    path.moveTo(l, t);//滑动起点
                    path.lineTo(l, t);//滑动终点
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                        builder.addStroke(new GestureDescription.StrokeDescription(path, 1L, duration, false));
                    } else {
                        builder.addStroke(new GestureDescription.StrokeDescription(path, 0L, duration));
                    }
                    GestureDescription description = builder.build();
                    QuickAccessibilityService.instance.dispatchGesture(description, null, null);
                    return true;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    public static boolean touchPoint(int x, int y) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            GestureDescription.Builder builder = new GestureDescription.Builder();
            try {
                Random random = new Random();
                long duration = 120 + random.nextInt(60);
                Path path = new Path();
                path.moveTo(x, y);//滑动起点
                path.lineTo(x, y);//滑动终点
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    builder.addStroke(new GestureDescription.StrokeDescription(path, 1L, duration, false));
                } else {
                    builder.addStroke(new GestureDescription.StrokeDescription(path, 0L, duration));
                }
                GestureDescription description = builder.build();
                QuickAccessibilityService.instance.dispatchGesture(description, null, null);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    public static boolean moveNode(Path path) {
        return move(path, 700);
    }

    public static boolean move(Path path, long duration) {
        if (QuickAccessibilityService.instance != null && path != null) {
            GestureDescription.Builder builder = null;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                builder = new GestureDescription.Builder();
                GestureDescription description = null;
                try {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                        builder.addStroke(new GestureDescription.StrokeDescription(path, 1L, duration, false));
                    } else {
                        builder.addStroke(new GestureDescription.StrokeDescription(path, 0L, duration));
                    }

                    description = builder.build();
                    QuickAccessibilityService.instance.dispatchGesture(description, new AccessibilityService.GestureResultCallback() {
                        @Override
                        public void onCompleted(GestureDescription gestureDescription) {
                            super.onCompleted(gestureDescription);
                            // Log.d(TAG,"滑动结束");
                        }

                        @Override
                        public void onCancelled(GestureDescription gestureDescription) {
                            super.onCancelled(gestureDescription);
                            //Log.d(TAG,"滑动取消");
                        }
                    }, null);
                    return true;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                //向上滚动
                AccessibilityNodeInfo nodeInfo = QuickAccessibilityService.instance.getRootInActiveWindow();//.performAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
//                while (nodeInfo != null) {
//                    if (nodeInfo.isScrollable()) {
//                        nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
//                        return true;
//                    }
//                    nodeInfo = nodeInfo.getParent();
//                }
            }
        }
        return false;
    }

    /**
     * 是否可以上滑
     *
     * @param nodeInfo
     * @return
     */
    public static boolean canScrollUp(AccessibilityNodeInfo nodeInfo) {
        int screenWidth = DisplayUtil.getScreenWidth(QuickAccessibilityService.instance);
        int screenHeight = DisplayUtil.getScreenHeight(QuickAccessibilityService.instance);
        //Rect rect = QuickAccessibilityHelper.getBundsInScreen(nodeInfo);1
        Rect rect = new Rect();//
        nodeInfo.getBoundsInScreen(rect);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {//存在控件高度为负数的情况 如位置：Rect(71, 2323 - 506, 2266)(l=71,t=2323,r=506,b=2266)
            Log.d(TAG,"控件位置：(" + screenWidth + "," + screenHeight + "),位置：" + rect + "(l=" + rect.left + ",t=" + rect.top + ",r=" + rect.right + ",b=" + rect.bottom + "),nodeInfo Id=" + nodeInfo.getViewIdResourceName() + ",Text=" + nodeInfo.getText() + ",Description=" + nodeInfo.getContentDescription()+",nodeInfo="+nodeInfo);
        }
        return (screenHeight/2) < (rect.top + Math.abs(rect.height()));
    }

}
